import os
import random
import time

from matplotlib import pyplot as plt

from dataset import generate_dataset
from utils import save_variable
from bruteforce import convex_hull_bruteforce
from graham_scan import graham_scan
from divide_and_conquer import convex_hull_d_c


def draw(points, convex_hull, _output_path):
    fig, ax = plt.subplots(figsize=(6, 6))

    x, y = [point[0] for point in points], [point[1] for point in points]

    ax.scatter(x, y, s=10, c='red', marker='o')

    for i in range(1, len(convex_hull) + 1):
        x, y = [convex_hull[i - 1][0], convex_hull[i % len(convex_hull)][0]], [convex_hull[i - 1][1],
                                                                               convex_hull[i % len(convex_hull)][1]]
        ax.plot(x, y, marker='', color='blue', alpha=1, linewidth=3)

    ax.set(xlim=(0, 100), xticks=range(0, 101, 10),
           ylim=(0, 100), yticks=range(0, 101, 10))

    plt.grid()
    ax.set_box_aspect(1)
    if _output_path is not None:
        plt.savefig(_output_path)
        if not _output_path.endswith('.svg'):
            if _output_path.endswith('.png'):
                _output_path = _output_path[:-4]
            plt.savefig(_output_path + '.svg')
    else:
        plt.show()
    plt.close()
    # plt.show()


if __name__ == '__main__':
    configs = [
        {
            'name': 'bruteforce',
            'func': convex_hull_bruteforce
        },
        {
            'name': 'graham_scan',
            'func': graham_scan
        },
        {
            'name': 'divide_and_conquer',
            'func': convex_hull_d_c
        },
        {
            'name': 'graham_scan_self_quicksort',
            'func': graham_scan
        },
    ]
    config = configs[0]
    name = config['name']
    func = config['func']
    dataset_sizes = list(range(1000, 11000, 1000))
    run_times = 20

    print('name:', name)
    print('func:', func)
    print('dataset_sizes:', dataset_sizes)
    output_path = os.path.join('results', name)
    os.makedirs(output_path, exist_ok=True)
    rand = random.Random()
    # rand.seed(7)

    consumes = []
    # for i in range(3, 6):
    #     random.seed(i)
    #     print('seed:', i)
    for dataset_size in dataset_sizes:
        print('dataset size:', dataset_size)

        datasets = [generate_dataset(dataset_size, (0, 100), (0, 100), rand) for i in range(run_times)]
        # dataset = [(20, 20), (20, 80), (80, 20), (80, 80)]
        dataset_copys = [dataset[:] for dataset in datasets]

        start = time.time()
        last_result = None
        for i in range(run_times):
            last_result = func(dataset_copys[i])
        elapsed = (time.time() - start) / run_times
        consumes.append(elapsed)

        draw(datasets[-1], last_result,
             _output_path=os.path.join(output_path, f'figure-{dataset_size}'))
        print('time consume:', elapsed * 1000, 'ms')
        # print('convex_num:', len(_convex_hull))
        print('=' * 50)

    result = {
        'run_times_per_dataset': run_times,
        'dataset_sizes': dataset_sizes,
        'avg_time_consumes': consumes
    }
    print('data:', result)
    save_variable(result, os.path.join(output_path, 'data.pkl'))
